#ifndef _CORELDBGHELP_H_
#define _CORELDBGHELP_H_

#include "StdAfx.h"
#include "../DbgHelp/Inc/dbghelp.h"

//#define USE_SYSTEM_DBGHELP_DLL

#ifdef USE_SYSTEM_DBGHELP_DLL
class CCorelDbgHelp
{
public:
    CCorelDbgHelp(){}
    ~CCorelDbgHelp(){}

public:
    DWORD SymCleanup(HANDLE hProcess) 
    {
        return ::SymCleanup(hProcess);
    }

    DWORD SymSetOptions(DWORD SymOptions)
    {
        return ::SymSetOptions(SymOptions);
    }

    BOOL SymInitializeA(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
    {
        return ::SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
    }

    BOOL SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess)
    {
        return ::SymInitializeW(hProcess, UserSearchPath, fInvadeProcess);
    }

    DWORD64 SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
    {
        return ::SymLoadModule64(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll);
    }

    BOOL StackWalk64(
        DWORD MachineType,
        HANDLE hProcess,
        HANDLE hThread,
        LPSTACKFRAME64 StackFrame,
        PVOID ContextRecord,
        PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
        PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
        PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
        PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress)
    {
        return ::StackWalk64(MachineType, hProcess, hThread, StackFrame, ContextRecord, ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine, TranslateAddress);
    }

    static PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
    {
        return ::SymFunctionTableAccess64(hProcess, AddrBase);
    }

    static DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 qwAddr)
    {
        return ::SymGetModuleBase64(hProcess, qwAddr);
    }

    BOOL SymGetModuleInfo64(HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULE64 ModuleInfo)
    {
        return ::SymGetModuleInfo64(hProcess, qwAddr, ModuleInfo);
    }

    BOOL SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol)
    {
        return ::SymFromAddr(hProcess, Address, Displacement, Symbol);
    }

    BOOL SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
    {
        return ::SymGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
    }
};
#else
class CCorelDbgHelp
{
public:
    CCorelDbgHelp();
    ~CCorelDbgHelp();

public:
    DWORD SymCleanup(HANDLE hProcess) 
    {
        return m_pfnSymCleanup(hProcess);
    }

    DWORD SymSetOptions(DWORD SymOptions)
    {
        return m_pfnSymSetOptions(SymOptions);
    }

    BOOL SymInitializeA(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
    {
        return m_pfnSymInitializeA(hProcess, UserSearchPath, fInvadeProcess);
    }

    BOOL SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess)
    {
        return m_pfnSymInitializeW(hProcess, UserSearchPath, fInvadeProcess);
    }

    DWORD64 SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
    {
        return m_pfnSymLoadModule64(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll);
    }

    BOOL StackWalk64(
        DWORD MachineType,
        HANDLE hProcess,
        HANDLE hThread,
        LPSTACKFRAME64 StackFrame,
        PVOID ContextRecord,
        PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
        PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
        PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
        PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress)
    {
        return m_pfnStackWalk64(MachineType, hProcess, hThread, StackFrame, ContextRecord, ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine, TranslateAddress);
    }

    static PVOID SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
    {
        return g_pfnSymFunctionTableAccess64(hProcess, AddrBase);
    }

    static DWORD64 SymGetModuleBase64(HANDLE hProcess, DWORD64 qwAddr)
    {
        return g_pfnSymGetModuleBase64(hProcess, qwAddr);
    }

    BOOL SymGetModuleInfo64(HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULE64 ModuleInfo)
    {
        return m_pfnSymGetModuleInfo64(hProcess, qwAddr, ModuleInfo);
    }

    BOOL SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol)
    {
        return m_pfnSymFromAddr(hProcess, Address, Displacement, Symbol);
    }

    BOOL SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
    {
        return m_pfnSymGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
    }

private:
    HMODULE m_hModule;

    typedef DWORD (WINAPI *PFN_SymCleanup)(HANDLE hProcess);
    PFN_SymCleanup m_pfnSymCleanup;

    typedef DWORD (WINAPI *PFN_SymSetOptions)(DWORD SymOptions);
    PFN_SymSetOptions m_pfnSymSetOptions;

    typedef BOOL (WINAPI *PFN_SymInitializeA)(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess);
    PFN_SymInitializeA m_pfnSymInitializeA;

    typedef BOOL (WINAPI *PFN_SymInitializeW)(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess);
    PFN_SymInitializeW m_pfnSymInitializeW;

    typedef DWORD64 (WINAPI *PFN_SymLoadModule64)(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll);
    PFN_SymLoadModule64 m_pfnSymLoadModule64;

    typedef BOOL (WINAPI *PFN_StackWalk64)(DWORD MachineType,
                                           HANDLE hProcess,
                                           HANDLE hThread,
                                           LPSTACKFRAME64 StackFrame,
                                           PVOID ContextRecord,
                                           PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
                                           PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
                                           PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
                                           PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
    PFN_StackWalk64 m_pfnStackWalk64;

    typedef PVOID (WINAPI *PFN_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
    static PFN_SymFunctionTableAccess64 g_pfnSymFunctionTableAccess64;

    typedef DWORD64 (WINAPI *PFN_SymGetModuleBase64)(HANDLE hProcess, DWORD64 qwAddr);
    static PFN_SymGetModuleBase64 g_pfnSymGetModuleBase64;

    typedef BOOL (WINAPI *PFN_SymGetModuleInfo64)(HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULE64 ModuleInfo);
    PFN_SymGetModuleInfo64 m_pfnSymGetModuleInfo64;

    typedef BOOL (WINAPI *PFN_SymFromAddr)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol);
    PFN_SymFromAddr m_pfnSymFromAddr;

    typedef BOOL (WINAPI *PFN_SymGetLineFromAddr)(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line);
    PFN_SymGetLineFromAddr m_pfnSymGetLineFromAddr;
};
#endif // USE_SYSTEM_DBGHELP_DLL

#endif // _CORELDBGHELP_H_